<template>
  <el-row>
    <el-col :span="8">
      <el-card>
        <template #header>
          <div class="card-header">
            <el-link
              href="https://v3.cn.vuejs.org/api/sfc-script-setup.html"
              target="_blank"
              >Vue3.2.25 setup语法糖
            </el-link>
            <el-icon
              class="copy-button"
              size="20"
              @click="handleCopy(v3SetupCode)"
            >
              <copy-document />
            </el-icon>
          </div>
        </template>
        <pre class="language-javascript">
          <code v-html='v3SetupHtml'></code>
        </pre>
      </el-card>
    </el-col>
    <el-col :span="8">
      <el-card>
        <template #header>
          <div class="card-header">
            <span class="el-link">Vue3.2.25</span>
            <el-icon class="copy-button" size="20" @click="handleCopy(v3Code)">
              <copy-document />
            </el-icon>
          </div>
        </template>
        <pre class="language-javascript">
          <code v-html='v3Html'></code>
        </pre>
      </el-card>
    </el-col>
    <el-col :span="8">
      <el-card>
        <template #header>
          <div class="card-header">
            <span class="el-link">Vue2+</span>
            <el-icon class="copy-button" size="20" @click="handleCopy(v2Code)">
              <copy-document />
            </el-icon>
          </div>
        </template>
        <pre class="language-javascript">
          <code v-html='v2Html'></code>
        </pre>
      </el-card>
    </el-col>
  </el-row>
</template>

<script setup>
import { getCurrentInstance } from 'vue'
import _ from 'lodash'
import Prism from 'prismjs'
import 'prismjs/plugins/line-numbers/prism-line-numbers.js'
import 'prismjs/themes/prism-okaidia.css'
import 'prismjs/plugins/line-numbers/prism-line-numbers.css'

const { proxy } = getCurrentInstance()
const handleCopy = _.debounce(
  value => {
    const input = document.createElement('input')
    input.setAttribute('value', value)
    document.body.appendChild(input)
    input.select()
    if (document.execCommand('copy')) {
      document.execCommand('copy')
      proxy.$message({ type: 'success', message: '代码已复制到剪切板' })
    }
    document.body.removeChild(input)
  },
  500,
  {
    leading: true,
    trailing: false
  }
)

const v3SetupCode = `
<script setup>
import {ref, reactive, toRefs, watch, getCurrentInstance} from 'vue'
import { getUser, updateUser } from '@/api/user'

const props = defineProps({
  visible: false,
  id: {
    required: true,
    type: Number
  }
})
const emit = defineEmits(['closed', 'success'])
const { proxy } = getCurrentInstance()
const formRef = ref()
const state = reactive({
  isShow: false,
  initLoading: true,
  submitLoading: false,
  form: {},
  rules: reactive({
    phone: [
      {
        required: true,
        message: '请输入手机号',
        trigger: 'blur',
      },
      {
        pattern: /^[1][0-9]{10}$/,
        message: '请输入正确的手机号格式',
        trigger: 'blur',
      },
    ],
    name: [
      {
        required: true,
        message: '请输入姓名',
        trigger: 'blur',
      },
      {
        min: 2,
        max: 30,
        message: '2至30个字符',
        trigger: 'blur',
      }
    ]
  })
})

const handleClose = (done) => {
  if (typeof done === 'function') {
    done()
  }
  formRef.value.resetFields()
  emit('closed')
}
const handleSubmit = () => {
  formRef.value.validate((valid) => {
    if (valid) {
      state.submitLoading = true
      state.form.id = props.id
      updateUser(state.form)
          .then(() => {
            emit('success')
            handleClose()
          })
          .catch(e => proxy.$message({
            type: 'error',
            message: e.msg
          }))
          .finally(() => state.submitLoading = false)
    }
  })
}

watch(() => props.visible, (newValue, oldValue) => {
  if (newValue) {
    state.initLoading = true
    state.submitLoading = true
    getUser(props.id)
        .then(res => state.form = res.data)
        .finally(() => {
          state.initLoading = false
          state.submitLoading = false
        })
  }
  state.isShow = newValue
})

const {isShow, initLoading, submitLoading, form, rules} = toRefs(state)
<\/script>`
const v3SetupHtml = Prism.highlight(
  v3SetupCode,
  Prism.languages.javascript,
  'javascript'
)

const v3Code = `
<script>
import {ref, reactive, toRefs, watch, getCurrentInstance} from 'vue'
import { getUser, updateUser } from '@/api/user'

export default {
  props: {
    visible: false,
    id: {
      required: true,
      type: Number
    }
  },
  emits: ['closed', 'success'],
  setup(props, context) {
    const { proxy } = getCurrentInstance()
    const formRef = ref()
    const state = reactive({
      isShow: false,
      initLoading: true,
      submitLoading: false,
      form: {},
      rules: reactive({
        phone: [
          {
            required: true,
            message: '请输入手机号',
            trigger: 'blur',
          },
          {
            pattern: /^[1][0-9]{10}$/,
            message: '请输入正确的手机号格式',
            trigger: 'blur',
          },
        ],
        name: [
          {
            required: true,
            message: '请输入姓名',
            trigger: 'blur',
          },
          {
            min: 2,
            max: 30,
            message: '2至30个字符',
            trigger: 'blur',
          }
        ]
      })
    })

    const handleClose = (done) => {
      if (typeof done === 'function') {
        done()
      }
      formRef.value.resetFields()
      context.emit('closed')
    }
    const handleSubmit = () => {
      formRef.value.validate((valid) => {
        if (valid) {
          state.submitLoading = true
          state.form.id = props.id
          updateUser(state.form)
              .then(() => {
                context.emit('success')
                handleClose()
              })
              .catch(e => proxy.$message({
                type: 'error',
                message: e.msg
              }))
              .finally(() => state.submitLoading = false)
        }
      })
    }

    watch(() => props.visible, (newValue, oldValue) => {
      if (newValue) {
        state.initLoading = true
        state.submitLoading = true
        getUser(props.id)
            .then(res => state.form = res.data)
            .finally(() => {
              state.initLoading = false
              state.submitLoading = false
            })
      }
      state.isShow = newValue
    })

    return {formRef, ...toRefs(state), handleClose, handleSubmit}
  }
}
<\/script>`
const v3Html = Prism.highlight(v3Code, Prism.languages.javascript, 'javascript')

const v2Code = `
<script>
import { getUser, updateUser } from '@/api/user'

export default {
  props: {
    visible: false,
    id: {
      required: true,
      type: Number
    }
  },
  data() {
    return {
      isShow: false,
      initLoading: true,
      submitLoading: false,
      form: {},
      rules: {
        phone: [
          {
            required: true,
            message: '请输入手机号',
            trigger: 'blur',
          },
          {
            pattern: /^[1][0-9]{10}$/,
            message: '请输入正确的手机号格式',
            trigger: 'blur',
          },
        ],
        name: [
          {
            required: true,
            message: '请输入姓名',
            trigger: 'blur',
          },
          {
            min: 2,
            max: 30,
            message: '2至30个字符',
            trigger: 'blur',
          }
        ]
      }
    }
  },
  methods: {
    handleClose(done) {
      if (typeof done === 'function') {
        done()
      }
      this.$refs.formRef.resetFields()
      this.$emit('closed')
    },
    handleSubmit() {
      this.$refs.formRef.validate((valid) => {
        if (valid) {
          this.submitLoading = true
          this.form.id = this.id
          updateUser(this.form)
              .then(() => {
                this.$emit('success')
                this.handleClose()
              })
              .catch(e => this.$message({
                type: 'error',
                message: e.msg
              }))
              .finally(() => this.submitLoading = false)
        }
      })
    }
  },
  watch: {
    visible(newValue, oldValue) {
      if (newValue) {
        this.initLoading = true
        this.submitLoading = true
        getUser(this.id)
            .then(res => this.form = res.data)
            .finally(() => {
              this.initLoading = false
              this.submitLoading = false
            })
      }
      this.isShow = newValue
    }
  }
}
<\/script>`
const v2Html = Prism.highlight(v2Code, Prism.languages.javascript, 'javascript')
</script>

<style scoped>
:deep(.el-card__header) {
  padding: 10px 15px;
}

:deep(.el-card__body) {
  padding: 0;
}

:deep(pre[class*='language-']) {
  margin: 0;
  border-radius: 0;
}

.card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.copy-button {
  cursor: pointer;
}
</style>
